package com.example.kuaizu.service.imp;

import cn.hutool.json.JSONUtil;
import com.example.kuaizu.config.MQConfig;
import com.example.kuaizu.mapper.ProjectMapper;
import com.example.kuaizu.pojo.PageBean;
import com.example.kuaizu.pojo.ProjectJoin;
import com.example.kuaizu.pojo.ProjectReview;
import com.example.kuaizu.pojo.dto.ApplicationProjectListDTO;
import com.example.kuaizu.pojo.dto.UserEmailDao;
import com.example.kuaizu.pojo.ov.ProjectOv;
import com.example.kuaizu.pojo.ov.UserProfileOv;
import com.example.kuaizu.pojo.pram.JoinSubscribeMassageParam;
import com.example.kuaizu.pojo.pram.ProjcetIds;
import com.example.kuaizu.pojo.pram.projectDeliveryOliveBranchParam;
import com.example.kuaizu.service.InProjectService;
import com.example.kuaizu.utils.DateFromUtils;
import com.example.kuaizu.utils.ThreadLocalUtil;
import com.example.kuaizu.utils.UserUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import kuaizu.common.PageData;
import kuaizu.common.constp.KuaiZuConst;
import kuaizu.common.exception.MassageException;
import kuaizu.common.mqconst.MQConstant;
import kuaizu.common.param.QueryDataPoJectInfoPram;
import kuaizu.common.tablepojo.Project;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.mybatis.spring.MyBatisSystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import static kuaizu.common.constp.KuaiZuConst.ERROR;

@Service
public class ProjectService implements InProjectService {
    private static final Logger log = LoggerFactory.getLogger(ProjectService.class);
    @Autowired
    ProjectMapper projectMapper;
    //线程池
    @Autowired
    private ThreadPoolTaskExecutor customThreadPool;

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private SubscribeMassageService subscribeMassageService;

    //创建项目
    @Override
    @Transactional
    public Project createProject(Project pro) {
        //查询是否存在该项目
        try {
            projectMapper.selectProjectId(new Project(pro.getCreatorOpenid(), pro.getProjectName()));
        } catch (MyBatisSystemException | TooManyResultsException e) {
            throw new MassageException(ERROR, "项目已将创建,换个名字试试");
        }
        //检查规定的数据是否存在
        //将openid添加到项目中去
        Map<String, Object> user = ThreadLocalUtil.get();
        //将map对象转成user对象
        pro.setLookcount(0L);
        pro.setApplicationCount(0L);
        //设置openid
        pro.setCreatorOpenid(user.get("openid").toString());
        if (null == pro.getSchool()) {
            pro.setSchool(Integer.valueOf(user.get("school").toString()));
        }
        //创建时间
        pro.setCreatedAt(DateFromUtils.getNowDate());
        pro.setUpdatedAt(DateFromUtils.getNowDate());
        //审核设置为未审核
        pro.setAuditStatus(KuaiZuConst.PROJECT_NO);
        System.out.println(pro);
        //判断是否邮件推广
        if (pro.getEmailPromotion()) {
            //TODO邮件推广
            System.out.println("邮件推广");
        }
        projectMapper.createProject(pro);
        //根据项目信息查询项目id
        Project project = projectMapper.selectProjectId(new Project(pro.getCreatorOpenid(), pro.getProjectName()));
        log.info("项目信息:{}", project);
        //将对象持久化发送到mq队列中
        //rabbitTemplate.convertAndSend(MQConstant.CREATE_PROJECT_QUEUE,project);
        return project;
    }

    //申请加入项目
    @Transactional
    @Override
    public int joinProject(Integer projectid) {
        Map<String, Object> user = ThreadLocalUtil.get();
        //判断是否重复加入
        ProjectJoin por = projectMapper.selectProjectJoin(projectid, user.get("openid").toString());
        if (por != null) {
            throw new MassageException(ERROR, "您已经加入过该项目");
        }
        //自己不能加入自己的项目
        Project pro = projectMapper.SelectProjectInfo(projectid);
        if (pro.getCreatorOpenid().equals(user.get("openid").toString())) {
            throw new MassageException(ERROR, "您不能加入自己的项目");
        }
        //另开线程将项目的投递人数+1
        customThreadPool.execute(() -> {
            //
            projectMapper.updateApplicationCount(pro.getId());
        });
        //
        ProjectReview projectJoin = new ProjectReview();
        projectJoin.setProjectId(projectid);
        projectJoin.setOpenid(user.get("openid").toString());
        //设置加入项目初始化 0未处理 1已通过 2已拒绝
        projectJoin.setIsApproved(KuaiZuConst.NOCHECK);
        projectJoin.setApplicationTime(DateFromUtils.getNowDate());
        System.out.println(projectJoin);
        if (projectJoin.getProjectId() == null) {
            throw new RuntimeException("项目id不能为空");
        }
        return projectMapper.joinProject(projectJoin);
    }


    //查询所有的项目
    @Override
    @Transactional
    public List<ProjectOv> SelectProjectInfo(String openid) {
        List<ProjectOv> list = projectMapper.SelectProjectList(openid);
        return list;
    }

    //项目申请审核
    @Override
    @Transactional
    public int UpdateProjectJoin(Integer projectid, String id, Integer status) {
        if (projectid == null || id == null || status == null) {
            throw new MassageException(ERROR, "参数不能为空");
        }
        switch (status) {
            case 1:
                status = KuaiZuConst.CHECKPASS;
                break;
            case 2:
                status = KuaiZuConst.CHECKNO;
                break;
            default:
                throw new MassageException(ERROR, "状态码错误");
        }
        int o = projectMapper.UpdateProjectJoin(projectid, id, status);
        //向mq发送消息提醒投递人项目审核情况
        JoinSubscribeMassageParam parm = new JoinSubscribeMassageParam();
        parm.setProjectId(projectid);
        parm.setOpenId(id);
        //获取当前人信息
        Map<String, Object> map = ThreadLocalUtil.get();
        parm.setName(map.get("nickname").toString());
        parm.setStatus(KuaiZuConst.CHECKPASS.equals(status));
        rabbitTemplate.convertAndSend(MQConstant.PROJECT_JOIN_QUEUE, parm);
        return o;
    }

    //分页查询项目信息
    @Override
    @Transactional
    public PageBean<ProjectOv> getAllProject(Integer pageNum, Integer pageSize, Integer schoolid) {
        //创建pageBean对象
        PageBean<ProjectOv> pd = new PageBean<>();
        //开启分夜茶叙 使用分页查询插件 导入坐标  当前页码 ,每页的数据
        PageHelper.startPage(pageNum, pageSize);
        //调用mapper查询
        Map<String, Object> map = ThreadLocalUtil.get();
        List<ProjectOv> as = new LinkedList<>();
        try {
            as = projectMapper.selectAllProjectList(schoolid);
        } finally {
            PageHelper.clearPage();
        }
        //page中提供了方法可以获取pageHelper分页查询的结果 总数据条数,和当前页数据不强转看不到
        Page<ProjectOv> p = (Page<ProjectOv>) as;
        //把数据填充到pagebean中去
        pd.setItems(p.getResult());//获取指定页的数据
        pd.setTotal(p.getTotal());//获取总条数
        return pd;
    }

    //查询指定项目申请人信息,通过审核的信息
    @Override
    @Transactional
    public List<UserEmailDao> selectProjectJoin(Integer id, Integer status) {
        //查询项目的申请人的信息
        return projectMapper.selectUserEmailDao(id, status);
    }

    @Override
    @Transactional
    public List<UserProfileOv> selectProjectJoin2(Integer id, Integer start) {
        //在sql设置指定的字段判断即可
        return projectMapper.selectProjectUserJoin(id, start);
    }

    /**
     * 获取当前登录用户申请的所有项目列表以及项目信息
     *
     * @return 申请列表
     */
    @Override
    @Transactional
    public List<ApplicationProjectListDTO> queryApplicationProject() {
        log.info("查询项目审核信息");
        Map<String, Object> map = ThreadLocalUtil.get();
        String openid = (String) map.get("openid");
        log.info("openid:{}", openid);
//        String openid = "of5t47ayRQFRxb5hiVtA8sfWtdOs";
        List<ApplicationProjectListDTO> apds = projectMapper.queryApplicationProject(openid);
        for (ApplicationProjectListDTO apd : apds) {
            if (apd.getIsApproved() == 0) {
                apd.setPhone(null);
                apd.setEmail(null);
                apd.setNickname(null);
            }
        }
        return apds;
    }

    //增加阅读量
    @Override
    @Transactional
    public void updeateLookProject(Integer id) {
        projectMapper.updateLookProject(id);
    }

    //删除项目
    @Transactional
    @Override
    public void deleteProject(Integer id) {
        //将项目赋值到项目删除表中去
        Project pro = projectMapper.SelectProjectInfo(id);
        if (pro == null) {
            throw new MassageException(ERROR, "项目不存在");
        }
        //开启线程用来做项目复制
        //customThreadPool.execute(() -> {
        //    //
        //    projectMapper.copyProjectToDelectTable(pro);
        //});
        //删除项目审核表中的信息
        projectMapper.delectProjectReview(id);
        projectMapper.delectEmailPromotion(id);
        //删除消息推广表中的项目信息

        //删除项目
        projectMapper.deleteProject(id);
        //删除es
        rabbitTemplate.convertAndSend(MQConstant.DELECT_PROJECT_QUEUE, id);
    }

    //根据项目id查询项目信息
    @Override
    @Transactional
    public ProjectOv selectProjectById(String id) {
        return projectMapper.selectProjectById(id);
    }

    //撤销申请的项目
    @Override
    @Transactional
    public void revoke(Integer id) {
        //获取用户信息
        Map<String, Object> user = ThreadLocalUtil.get();
        //拿到openid
        String openid = (String) user.get("openid");
        //去数据库删除对应的信息
        projectMapper.delectJoinProject(id, openid);
    }

    //是否加入项目
    @Override
    @Transactional
    public boolean isjoin(Integer id) {
        //获取用户信息
        Map<String, Object> user = ThreadLocalUtil.get();
        ProjectJoin open = projectMapper.isJoin(user.get("openid").toString(), id);
        return open != null;
    }


    @Override
    public PageData<ProjectOv> queryProjectByIntroduce(QueryDataPoJectInfoPram pram) {
        //向es服务发送消息
        PageData<ProjectOv> data = new PageData<>();
        return send(pram, data, PageData.class, "/project/queryDatapPojectInfo");
    }

    @Override
    public PageData<ProjectOv> queryProjectByskillSummary(QueryDataPoJectInfoPram pram) {
        //向es服务发送消息
        PageData<ProjectOv> data = new PageData<>();
        return send(pram, data, PageData.class, "/project/queryProjectBySkillDetails");
    }

    /**
     * 根据id获取项目信息
     *
     * @param projectIds
     * @return
     */
    @Override
    public List<ProjectOv> byProjectIds(ProjcetIds projectIds) {
        return projectMapper.selectProjectByIds(projectIds);
    }

    @Override
    public void projectReview(Integer projectId, String openId) {
        //审核通过
        projectMapper.projectReview(projectId, openId);
    }

    /**
     * 查看项目投递的人才
     *
     * @param req
     * @return
     */
    @Override
    public List<UserProfileOv> projectDeliveryOliveBranch(projectDeliveryOliveBranchParam req) {
        String openId = UserUtils.getOpenId();
        List<UserProfileOv> users = projectMapper.projectDeliveryOliveBranch(req.getId(), openId);
        return users;
    }

    public <T, V> T send(V data, T resData, Class<T> resType, String url) {
        String json = restTemplate.execute("http://127.0.0.1:8083" + url, HttpMethod.POST, req -> {
            //设置请求体 携带对应的数据 将对应的对象转成json字符串
            // 将对象转换为 JSON 字符串
            req.getHeaders().setContentType(org.springframework.http.MediaType.parseMediaType("application/json; charset=UTF-8"));
            String jsonBody = objectMapper.writeValueAsString(data);
            //设置请求体
            OutputStream out = req.getBody();
            out.write(jsonBody.getBytes(StandardCharsets.UTF_8));
            out.flush();
            log.info("转换成的json->{}", jsonBody);
        }, response -> {
            // 处理响应
            log.info("接相应");
            if (response.getStatusCode().is2xxSuccessful()) {
                // 读取响应内容
                byte[] body = response.getBody().readAllBytes();
                log.debug("相应内容{}", new String(body));
                return new String(body);
            } else {
                throw new RuntimeException("请求失败，状态码: " + response.getStatusCode());
            }
        });
        Map bean = JSONUtil.toBean(json, Map.class);
        if (CollectionUtils.isEmpty(bean)) {
            return null;
        }
        try {
            resData = objectMapper.readValue(json, resType);
        } catch (JsonProcessingException e) {
            throw new MassageException("序列化失败");
        }
        return resData;
    }

    //向队列发送消息
    public void sendMessage(String message) {
        rabbitTemplate.convertAndSend(MQConfig.PROJECT_SEND_QUEUE, message);
    }

    @Override
    public void test() {
        rabbitTemplate.convertAndSend("duil", "mq能通?????");
    }


}
